﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.Communication.Base;
using UtilZ.Dotnet.Ex.Communication.Net.Base;
using UtilZ.Dotnet.Ex.ZLog;

namespace UtilZ.Dotnet.Ex.Communication.Net.Ftp
{
    internal partial class FtpSession
    {
        private IReadOnlyDictionary<string, DirectoryInfo> _pathDic = null;
        private const string _ROOT_PATH = "/";
        private string _ftpPath = _ROOT_PATH;


        public void InitFtpPathManager()
        {
            this._pathDic = this._ftpUser.PathDic;
        }



        private bool FtpPathIsRoot()
        {
            return this.FtpPathIsRoot(ref this._ftpPath);
        }

        private bool FtpPathIsRoot(ref string path)
        {
            return string.Equals(path, _ROOT_PATH);
        }

        public void Reset()
        {
            this._sessionStatus = FtpSessionStatus.NoAuth;
            this._ftpUser = null;
            this.Encoding = this._ftpServer.Config.Encoding;
            this._ftpPath = _ROOT_PATH;
        }


        /// <summary>
        /// 返回指定目录的文件名列表
        /// </summary>
        /// <returns></returns>
        public string NLST()
        {
            /**************************************************************
             *
             * 7z1805-x64.exe
             * IP 规划_new.xlsx
             * IP 规划_new.zip
             * wenjianjia
             * 台位报文
             * 新部署图.vsdx
             * 
             ***************************************************************/

            StringBuilder sb = new StringBuilder();
            DirectoryInfo dirInfo = this.GetFtpLocalPath(ref this._ftpPath);
            if (dirInfo != null && dirInfo.Exists)
            {
                FileSystemInfo[] fileSystemInfos = dirInfo.GetFileSystemInfos();
                foreach (var fileSystemInfo in fileSystemInfos)
                {
                    if (sb.Length > 0)
                    {
                        sb.Append(Environment.NewLine);
                    }
                    sb.Append(fileSystemInfo.Name);
                }
            }

            //Loger.Trace($"NLST\r\n{sb.ToString()}");
            return sb.ToString();
        }

        /// <summary>
        /// 如果指定了文件或目录，返回其信息；否则返回当前工作目录的信息
        /// </summary>
        /// <returns></returns>
        public string LIST()
        {
            /**************************************************************
           *
           * 11-06-18  08:31PM              1438086 7z1805-x64.exe
           * 03-24-21  05:41PM                21910 IP 规划_new.xlsx
           * 03-17-22  11:30AM                18452 IP 规划_new.zip
           * 03-17-22  11:30AM       <DIR>          wenjianjia
           * 03-17-22  11:30AM       <DIR>          台位报文
           * 03-24-21  05:52PM                34966 新部署图.vsdx
           * 
           ***************************************************************/

            StringBuilder sb = new StringBuilder();

            if (this.FtpPathIsRoot())
            {
                foreach (var kv in this._pathDic)
                {
                    if (sb.Length > 0)
                    {
                        sb.Append(Environment.NewLine);
                    }

                    //sb.Append(directoryInfo.CreationTime.ToString("MM-dd-yy hh:mm tt"));
                    sb.Append(kv.Value.CreationTime.ToString("MM-dd-yy hh:mm"));
                    sb.Append("       <DIR>          ");
                    sb.Append(kv.Key);
                }
            }
            else
            {
                DirectoryInfo dirInfo = this.GetFtpLocalPath(ref this._ftpPath);
                if (dirInfo != null && dirInfo.Exists)
                {
                    FileSystemInfo[] fileSystemInfos = dirInfo.GetFileSystemInfos();
                    FileInfo fileInfo;
                    DirectoryInfo directoryInfo;

                    foreach (var fileSystemInfo in fileSystemInfos)
                    {
                        if (fileSystemInfo is FileInfo)
                        {
                            if (sb.Length > 0)
                            {
                                sb.Append(Environment.NewLine);
                            }

                            fileInfo = (FileInfo)fileSystemInfo;
                            //sb.Append(fileInfo.CreationTime.ToString("MM-dd-yy hh:mm tt"));
                            sb.Append(fileInfo.CreationTime.ToString("MM-dd-yy hh:mm"));
                            sb.Append(string.Format("{0,21}", fileInfo.Length));
                            sb.Append(" ");
                            sb.Append(fileInfo.Name);

                        }
                        else if (fileSystemInfo is DirectoryInfo)
                        {
                            if (sb.Length > 0)
                            {
                                sb.Append(Environment.NewLine);
                            }

                            directoryInfo = (DirectoryInfo)fileSystemInfo;
                            //sb.Append(directoryInfo.CreationTime.ToString("MM-dd-yy hh:mm tt"));
                            sb.Append(directoryInfo.CreationTime.ToString("MM-dd-yy hh:mm"));
                            sb.Append("       <DIR>          ");
                            sb.Append(directoryInfo.Name);
                        }
                        else
                        {
                            ZLoger.Warn($"未知的文件类型\"{fileSystemInfo.ToString()}\",忽略");
                        }
                    }
                }
            }
            //Loger.Trace($"LIST\r\n{sb.ToString()}");
            return sb.ToString();
        }

        /// <summary>
        /// 改变到父目录
        /// </summary>
        public void CDUP()
        {
            //CDUP   /tmp/CoolEdit2.1/musicbianji/ -> /tmp/CoolEdit2.1/musicbianji/
            string ftpPath = this._ftpPath;
            if (!this.FtpPathIsRoot(ref ftpPath))
            {
                int index = ftpPath.LastIndexOf(PathEx.RightSlash);
                string newFtpPath = ftpPath.Substring(0, index + 1);
                if (!this.FtpPathIsRoot(ref newFtpPath))
                {
                    newFtpPath = newFtpPath.TrimEnd(PathEx.LeftSlash, PathEx.RightSlash);
                }

                this._ftpPath = newFtpPath;
                //Loger.Trace($"CDUP   {ftpPath} -> {this._ftpPath}");
            }
        }

        /// <summary>
        /// 改变工作目录
        /// </summary>
        /// <param name="commandLine"></param>
        public IFtpResponse CWD(string commandLine)
        {
            string dstPath = commandLine.Trim();
            if (!this.FtpPathIsRoot(ref dstPath))
            {
                if (dstPath.StartsWith(_ROOT_PATH))
                {
                    if (this.GetFtpLocalPath(ref dstPath) == null)
                    {
                        return new FtpCodeResponse(FtpStatusCodes.Code501, "The parameter must specify a valid directory");
                    }
                }
                else
                {
                    dstPath = PathEx.Combine(PathType.Web, this._ftpPath, dstPath);
                }
            }

            //Loger.Trace($"CWD   {this._ftpPath} -> {dstPath}");
            this._ftpPath = dstPath;
            return new FtpCodeResponse(FtpStatusCodes.Code250, "CWD command successful.");
        }

        /// <summary>
        /// 打印工作目录，返回主机的当前目录
        /// </summary>
        /// <returns></returns>
        public string PWD()
        {
            //Loger.Trace($"PWD   {this._ftpPath}");
            return $"\"{this._ftpPath}\" is current directory.";
        }

        /// <summary>
        /// 获取本地路径
        /// </summary>
        /// <param name="fileOrFolderName">文件名或文件夹名</param>
        /// <returns>本地路径</returns>
        public string GetLocalPath(string fileOrFolderName)
        {
            DirectoryInfo dirInfo = this.GetFtpLocalPath(ref this._ftpPath);
            if (dirInfo == null)
            {
                throw new ApplicationException($"ftp路径\"{this._ftpPath}\"无效.");
            }

            return PathEx.Combine(PathType.Local, dirInfo.FullName, fileOrFolderName);
        }


        private DirectoryInfo GetFtpLocalPath(ref string ftpPath)
        {
            int secondRightSlashIndex = -1;
            for (int i = 1; i < ftpPath.Length; i++)
            {
                if (ftpPath[i] == PathEx.RightSlash)
                {
                    secondRightSlashIndex = i - 1;
                    break;
                }
            }

            string key, subPath;
            if (secondRightSlashIndex > 0)
            {
                key = ftpPath.Substring(1, secondRightSlashIndex).ToLower();
                subPath = ftpPath.Substring(secondRightSlashIndex + 1);
            }
            else
            {
                key = ftpPath.Substring(1).ToLower();
                subPath = null;
            }

            DirectoryInfo dirInfo;
            if (this._pathDic.TryGetValue(key, out dirInfo))
            {
                string fullLocalPath = PathEx.Combine(PathType.Local, dirInfo.FullName, subPath);
                return new DirectoryInfo(fullLocalPath);
            }
            else
            {
                //无效路径应该返回null
                return null;
            }
        }

    }
}
